/**
 * 导航管理
 */
define(function (require, exports, module) {
    var $ = require("jquery");
    var util = require("util");
    var _ = require('underscore');
    var permission = require('permission');


    /**
     * @param {Element} el
     * @param {Array.<{id:string,code:string=,name:string,level:string,iconCls:string,url:Array.<string>,children:Array.<Object>=}>} mapData
     * @constructor
     */
    var NavManager = function (el, mapData) {
        this._$el = $(el);
        this._mapData = mapData;
        this._pathname = location.pathname;
        this._queryParams = util.getQueryParams(location.search);
        this._current = null;
        this._changeHandlers = [];
        this._flushed = false;
        /**
         * 权限类
         * @type {{string:boolean}}
         * @private
         */
        this._permissionMap = {};

        this.initMenuEvent();
        this.initTreeMenu();
    };

    NavManager.prototype = {
        /**
         * 初始化左侧树导航
         */
        initTreeMenu: function () {
            var self = this;

            //菜单初始化与权限相关
            permission.getData(function (permissionCodes) {
                var permissionObj = {};
                // 将数组转换成对象，可以加快权限对比的速度
                _.each(permissionCodes.nav || [], function (element) {
                    permissionObj[element] = true;
                });

                self._permissionMap = permissionObj;

                self.flush(self._mapData, self._permissionMap);
            });
        },
        /**
         * 刷新界面
         * @param {object} mapData
         * @param {{string:boolean}} permissionMap
         */
        flush: function (mapData, permissionMap) {
            var menuHtml = '';
            for (var i = 0, l = mapData.length; i < l; i++) {
                menuHtml += this.createMenuHtml(mapData[i], permissionMap);
            }
            this._$el.html(menuHtml);
            this._flushed = true;

            //触发document resize事件，调整嵌套iframe大小
            setTimeout(function () {
                $(document).trigger('resize');
            }, 0);
        },
        /**
         * 设置导航数据
         * @param {object} mapData
         */
        setMapData: function (mapData) {
            this._mapData = mapData;

            if (this._flushed) {
                this.flush(this._mapData, this._permissionMap);
            }
        },
        /**
         * 监听导航变化
         * @param {function(Object)} handler
         */
        addChangeHandler: function (handler) {
            this._changeHandlers.push(handler);
        },
        _fireChangeEvent: function () {
            var changeHandlers = this._changeHandlers;

            var handler;
            for (var i = 0; handler = changeHandlers[i]; i++) {
                handler(this._current);
            }
        },
        /**
         * 菜单是否有权限：只要有一个子菜单有权限就ok
         * @param nav
         * @param permissionObj
         */
        hasPermission: function (nav, permissionObj) {
            var hasPermission = false;
            if (nav.children) {
                _.each(nav.children || [], function (child) {
                    if (!child.code || permissionObj[child.code] === true) {
                        hasPermission = true;
                        return false;
                    }
                });
            } else {
                if (!nav.code || permissionObj[nav.code] === true) {
                    hasPermission = true;
                }
            }
            if (!hasPermission) {
                console.info('菜单' + nav.name + '没有权限');
            }
            return hasPermission;
        },
        /**
         * 创建左侧树导航
         * @param {object} navItem
         * @param {{string:boolean}} permissionObj
         * @returns {string}
         */
        createMenuHtml: function (navItem, permissionObj) {
            if (!this.hasPermission(navItem, permissionObj)) {
                return '';
            }

            var selected = this.isSelected(navItem);
            var children = navItem.children;

            var url = navItem["url"]; //菜单地址
            var target;
            if (url && url.length > 0) {
                url = url[0];
                target = navItem['target'] || '_self';
            } else {
                url = "javascript:void(0)";
                target = "";
            }

            var hasChildren = children && children.length > 0;
            var firstLevel = navItem["level"] === 1;

            var html = '<li id="' + navItem["id"] + '"';

            var navOnCls = firstLevel ? ' nav-selected nav-on' : ' nav-sub-selected nav-sub-on';

            var permissionClass = '';
            var permissionClassNames = this._getPermissionClassNames(children);
            if (navItem['code'] || permissionClassNames) {
                permissionClass = 'permission p-' + navItem["code"] + ' ' + permissionClassNames;
            }

            var modelClass = (navItem.cls || '') + ' ' + permissionClass + ' ' + (selected ? navOnCls : '');

            var strAttr = '';
            var attrs = navItem.attrs;
            if (attrs) {
                for (var key in attrs) {
                    if (key && attrs.hasOwnProperty(key)) {
                        strAttr += ' ' + key + '="' + attrs[key] + '"';
                    }
                }
            }

            html += 'class="' + modelClass + '"';
            html += '><a href="' + url + '" ' + (hasChildren || firstLevel ? 'class="nav-a"' : '') + ' target="' + target + '"' + strAttr + '>';
            if (firstLevel) {
                html += '<i class="' + navItem["iconCls"] + '"></i>';
            }
            html += navItem["name"] + '</a>';


            if (hasChildren) {
                html += '<ul class="nav-sub">';
                for (var i = 0, l = children.length; i < l; i++) {
                    html += this.createMenuHtml(children[i], permissionObj);
                }
                html += '</ul>';
            }

            if (!hasChildren && selected) {
                this._current = navItem;
                this._fireChangeEvent();
            }

            html += '</li>';
            return html;
        },
        /**
         * 判断两个url是否一致
         * @param {string} urlPattern
         * @returns {boolean}
         * @private
         */
        _isEqual: function (urlPattern) {
            var urlObj = util.getUrlObj(urlPattern);

            if (this._pathname !== urlObj.pathname) {
                return false;
            }

            var queryParamsPattern = util.getQueryParams(urlObj.search);
            queryParamsPattern['token'] = '{placeholder_}';

            var queryParamsCur = this._queryParams;

            var keysPattern = util.getKeys(queryParamsPattern);
            var keysCur = util.getKeys(queryParamsCur);

            //比较key是否一致
            var key;
            for (var i = 0; key = keysPattern[i]; i++) {
                if (queryParamsPattern[key] === '{placeholder_}') {
                    continue;
                } else if (queryParamsPattern[key] === '{placeholder}') {
                    if (typeof queryParamsCur[key] === 'undefined') {
                        return false;
                    }
                } else if (queryParamsCur[key] !== queryParamsPattern[key]) {
                    return false;
                }
            }
            for (var i = 0; key = keysCur[i]; i++) {
                if (queryParamsPattern[key] === '{placeholder_}') {
                    continue;
                } else if (queryParamsPattern[key] === '{placeholder}') {
                    if (typeof queryParamsCur[key] === 'undefined') {
                        return false;
                    }
                } else if (queryParamsCur[key] !== queryParamsPattern[key]) {
                    return false;
                }
            }

            return true;
        },
        /**
         * 是否选中，本身或者子孙选中时返回true
         * @param navItem
         * @returns {boolean}
         */
        isSelected: function (navItem) {
            var selected = false;
            var urls = navItem.url;
            if (urls) {
                var urlPattern;
                for (var i = 0; urlPattern = urls[i]; i++) {
                    selected = this._isEqual(urlPattern);

                    if (selected) {
                        break;
                    }
                }
            }

            var children = navItem.children;
            if (children) {
                var childItem;
                for (var i = 0; childItem = children[i]; i++) {
                    var temp = this.isSelected(childItem);
                    if (temp) {
                        selected = temp;
                        break;
                    }
                }
            }

            return selected;
        },
        /**
         * 获取权限类名
         * @param {Array} navItems
         * @returns {string}
         * @private
         */
        _getPermissionClassNames: function (navItems) {
            var classNames = [];

            if (navItems) {
                var item;
                for (var i = 0; item = navItems[i]; i++) {
                    if (item.code) {
                        classNames.push('p-' + item.code);
                    }

                    var childClassNameStr = this._getPermissionClassNames(item.children);
                    if (childClassNameStr) {
                        classNames.push(childClassNameStr);
                    }
                }
            }

            return classNames.join(' ');
        },
        /**
         *  初始化导航绑定事件
         */
        initMenuEvent: function () {
            this._$el
                .on('click', '.nav-a', function () {
                    var $this = $(this);
                    var parent = $this.parent();
                    var notSelected = !$this.hasClass('nav-selected');

                    if (parent.hasClass('nav-on') && notSelected) {
                        parent.removeClass('nav-on');
                    } else {
                        if (notSelected) {
                            parent.addClass('nav-on');
                        }
                    }
                })
                .on('click', 'a', function (e) {
                    //如果与目前导航地址一致，则禁止浏览器默认行为
                    var url = $(this).attr('href');
                    url = util.setUrlPara('token', util.getToken(), url);

                    var urlObj = util.getUrlObj(url);
                    if (urlObj.pathname + '?' + urlObj.search === location.pathname + location.search) {
                        e.preventDefault();
                        location.reload();
                    }
                })
        }
    };

    return NavManager;
});
